/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.form.editor.model.form.impl;

import java.rmi.server.UID;
import java.util.ArrayList;
import java.util.List;

import com.genia.toolbox.basics.editor.model.document.Element;
import com.genia.toolbox.basics.editor.model.document.VariableModel;
import com.genia.toolbox.basics.i18n.I18nMessage;
import com.genia.toolbox.web.gwt.form.client.form.impl.EnumDescriptableValuedItemEntryListImpl;
import com.genia.toolbox.web.gwt.form.server.spring.factory.EnumDescriptableValuedItemEntryListFactory;
import com.genia.toolbox.web.portlet.description.ContainerPortletDescription.LayoutDirection;

/**
 * The form model.
 */
public class FormModel
    implements Element<FormType>
{

  /**
   * The document ID.
   */
  private UID documentID;

  /**
   * The form ID.
   */
  private UID formID;

  /**
   * The form type.
   */
  private FormType type = FormType.HORIZONTAL;

  /**
   * The sub forms.
   */
  private List<FormModel> subElements = null;

  /**
   * The name.
   */
  private String name = null;

  /**
   * The form name.
   */
  private String elementName = null;

  /**
   * The description name.
   */
  private String descriptionName = null;

  /**
   * The description message.
   */
  private I18nMessage description = null;

  /**
   * Whether the form is a sub-form.
   */
  private boolean isSubElement = false;

  /**
   * The parent direction.
   */
  private LayoutDirection parentDirection = null;

  /**
   * The parent unique ID.
   */
  private UID parentID = null;

  /**
   * The form parameters.
   */
  private List<VariableModel> parameters = null;

  /**
   * Whether the form is enabled.
   */
  private boolean isEnabled = true;

  /**
   * Whether the form has entries.
   */
  private boolean hasEntries = false;

  /**
   * The form entries.
   */
  private List<VariableModel> entries = null;

  /**
   * The enum entry class.
   */
  private String enumEntry = null;

  /**
   * The label key.
   */
  private String labelKey = null;

  /**
   * Indicates if form can have a validator.
   */
  private boolean canHaveValidator = false;

  /**
   * The validatorClassName.
   */
  private String validatorClassName;

  /**
   * The validator parameters.
   */
  private List<VariableModel> validatorParameters;

  /**
   * The validator description name.
   */
  private String validatorDescriptionName;



  /**
   * Constructor.
   */
  public FormModel()
  {
    super();
    this.formID = new UID();
    this.parameters = new ArrayList<VariableModel>();
    this.entries = new ArrayList<VariableModel>();
    this.validatorParameters = new ArrayList<VariableModel>();
  }



  /**
   * getter of the canHaveValidator property.
   * 
   * @return canHaveValidator
   */
  public boolean canHaveValidator()
  {
    return canHaveValidator;
  }



  /**
   * setter of the canHaveValidator property.
   * 
   * @param canHaveValidator
   *          to set
   */
  public void setCanHaveValidator(boolean canHaveValidator)
  {
    this.canHaveValidator = canHaveValidator;
  }



  /**
   * getter of the validator class name property.
   * 
   * @return the validator class name
   */
  public String getValidatorClassName()
  {
    return validatorClassName;
  }



  /**
   * setter of the validator class name property.
   * 
   * @param validatorClassName
   *          to set
   */
  public void setValidatorClassName(String validatorClassName)
  {
    this.validatorClassName = validatorClassName;
  }



  /**
   * getter of the validator parameters property.
   * 
   * @return validator parameters
   */
  public List<VariableModel> getValidatorParameters()
  {
    return validatorParameters;
  }



  /**
   * setter of the validator parameters property.
   * 
   * @param validatorParameters
   *          to set
   */
  public void setValidatorParameters(List<VariableModel> validatorParameters)
  {
    this.validatorParameters = validatorParameters;
  }



  /**
   * getter of the validator description name property.
   * 
   * @return validator description name
   */
  public String getValidatorDescriptionName()
  {
    return validatorDescriptionName;
  }



  /**
   * setter of the validator description name property.
   * 
   * @param validatorDescriptionName
   *          to set
   */
  public void setValidatorDescriptionName(String validatorDescriptionName)
  {
    this.validatorDescriptionName = validatorDescriptionName;
  }



  /**
   * Get the document ID.
   * 
   * @return the document ID.
   */
  public UID getDocumentID()
  {
    return this.documentID;
  }



  /**
   * Set the document ID.
   * 
   * @param documentID
   *          the document ID.
   */
  public void setDocumentID(UID documentID)
  {
    this.documentID = documentID;
  }



  /**
   * Get the form unique ID.
   * 
   * @return the form unique ID.
   */
  public UID getUniqueID()
  {
    return this.formID;
  }



  /**
   * Get the form type.
   * 
   * @return the form type.
   */
  public FormType getType()
  {
    return this.type;
  }



  /**
   * Set the form type.
   * 
   * @param type
   *          the form type.
   */
  public void setType(FormType type)
  {
    this.type = type;
  }



  /**
   * Add a sub form.
   * 
   * @param form
   *          the sub form.
   */
  public void addSubElement(FormModel form)
  {
    this.subElements.add(form);
  }



  /**
   * Get the subforms.
   * 
   * @return the subforms.
   */
  public List<FormModel> getSubElements()
  {
    return this.subElements;
  }



  /**
   * Get the form name.
   * 
   * @return the form name.
   */
  public String getName()
  {
    return this.name;
  }



  /**
   * Set the form name.
   * 
   * @param name
   *          the form name.
   */
  public void setName(String name)
  {
    this.name = name;
  }



  /**
   * Get the form name.
   * 
   * @return the form name.
   */
  public String getElementName()
  {
    return this.elementName;
  }



  /**
   * Set the form name.
   * 
   * @param formName
   *          the form name.
   */
  public void setElementName(String formName)
  {
    this.elementName = formName;
  }



  /**
   * Get the form description.
   * 
   * @return the form description.
   */
  public I18nMessage getDescription()
  {
    return this.description;
  }



  /**
   * Set the form description.
   * 
   * @param description
   *          the form description.
   */
  public void setDescription(I18nMessage description)
  {
    this.description = description;
  }



  /**
   * Get the form description name.
   * 
   * @return the form description name.
   */
  public String getDescriptionName()
  {
    return this.descriptionName;
  }



  /**
   * Set the form description name.
   * 
   * @param descriptionName
   *          the form description name.
   */
  public void setDescriptionName(String descriptionName)
  {
    this.descriptionName = descriptionName;
  }



  /**
   * Get whether the form is a sub-form.
   * 
   * @return whether the form is a sub-form.
   */
  public boolean isSubElement()
  {
    return this.isSubElement;
  }



  /**
   * Set whether the form is a sub-form.
   * 
   * @param isSubElement
   *          whether the form is a sub-form.
   */
  public void setSubElement(boolean isSubElement)
  {
    this.isSubElement = isSubElement;
  }



  /**
   * Get the parent direction.
   * 
   * @return the parent direction.
   */
  public LayoutDirection getParentDirection()
  {
    return this.parentDirection;
  }



  /**
   * Set the parent direction.
   * 
   * @param parentDirection
   *          the parent direction.
   */
  public void setParentDirection(LayoutDirection parentDirection)
  {
    this.parentDirection = parentDirection;
  }



  /**
   * Update a sub-form.
   * 
   * @param updatedForm
   *          the updated form.
   */
  public void updateForm(FormModel updatedForm)
  {
    // Do nothing has there is no sub form.
  }



  /**
   * Get the form parent unique ID.
   * 
   * @return the form parent unique ID.
   */
  public UID getParentID()
  {
    return this.parentID;
  }



  /**
   * Set the form parent unique ID.
   * 
   * @param parentID
   *          the form parent unique ID.
   */
  public void setParentID(UID parentID)
  {
    this.parentID = parentID;
  }



  /**
   * Get the parameters.
   * 
   * @return the parameters.
   */
  public List<VariableModel> getParameters()
  {
    return parameters;
  }



  /**
   * Set the parameters.
   * 
   * @param parameters
   *          The parameters.
   */
  public void setParameters(List<VariableModel> parameters)
  {
    this.parameters = parameters;
  }



  /**
   * Get the entries.
   * 
   * @return the entries.
   */
  public List<VariableModel> getEntries()
  {
    return entries;
  }



  /**
   * Set the entries.
   * 
   * @param entries
   *          the entries.
   */
  public void setEntries(List<VariableModel> entries)
  {
    this.entries = entries;
  }



  /**
   * Get the enum class for the entry.
   * 
   * @return the enum class for the entry.
   */
  public String getEnumEntry()
  {
    return enumEntry;
  }



  /**
   * Set the enum class for the entry.
   * 
   * @param enumEntry
   *          the enum class for the entry.
   */
  public void setEnumEntry(String enumEntry)
  {
    this.enumEntry = enumEntry;
  }



  /**
   * Whether the form has entries.
   * 
   * @return true if the form has entries.
   */
  public boolean hasEntries()
  {
    return hasEntries;
  }



  /**
   * Set whether the form has entries.
   * 
   * @param hasEntries
   *          true if the form has entries.
   */
  public void setHasEntries(boolean hasEntries)
  {
    this.hasEntries = hasEntries;
  }



  /**
   * Get the label key.
   * 
   * @return the label key.
   */
  public String getLabelKey()
  {
    return labelKey;
  }



  /**
   * Set the label key.
   * 
   * @param labelKey
   *          the label key.
   */
  public void setLabelKey(String labelKey)
  {
    this.labelKey = labelKey;
  }



  /**
   * Whether the form is enabled.
   * 
   * @return true if the form is enabled.
   */
  public boolean isEnabled()
  {
    return this.isEnabled;
  }



  /**
   * Set whether the form is enabled.
   * 
   * @param isEnabled
   *          true if the form is enabled.
   */
  public void setIsEnabled(boolean isEnabled)
  {
    this.isEnabled = isEnabled;
  }



  /**
   * Get whether the element has at least one sub-element.
   * 
   * @return whether the element has at least one sub-element.
   */
  public boolean isContainer()
  {
    return false;
  }



  /**
   * Get whether the settings are valid.
   * 
   * @return whether the settings are valid.
   */
  public boolean accept()
  {
    boolean isOK = true;
    if (this.getName() == null || this.getName().trim().length() == 0) {
      isOK = false;
    }
    if (this.getLabelKey() == null || this.getLabelKey().trim().length() == 0) {
      isOK = false;
    }
    if (this.hasEntries) {
      boolean hasEnum = true;
      if (this.getEnumEntry() == null || this.getEnumEntry().trim().length() == 0) {
        hasEnum = false;
      }
      else {
        hasEnum = true;
        EnumDescriptableValuedItemEntryListImpl entries;
        try {
          EnumDescriptableValuedItemEntryListFactory entriesFactory = new EnumDescriptableValuedItemEntryListFactory();
          entriesFactory.setEnumClassName(this.getEnumEntry());
          entries = (EnumDescriptableValuedItemEntryListImpl) entriesFactory.getObject();
          if (entries == null) {
            isOK = false;
          }
        }
        catch (Exception e) {
          isOK = false;
        }
      }
      if (!hasEnum) {
        if (this.getEntries().isEmpty()) {
          isOK = false;
        }
        else {
          for (VariableModel variable : this.getEntries()) {
            if (!variable.accept()) {
              isOK = false;
              break;
            }
          }
        }
      }
    }
    for (VariableModel variable : this.getParameters()) {
      if (!variable.accept()) {
        isOK = false;
        break;
      }
    }
    for (VariableModel variable : this.getValidatorParameters()) {
      if (!variable.accept()) {
        isOK = false;
        break;
      }
    }
    return isOK;
  }

}
